function header(t,r,   i,needs) {
    split("name,col,string,use,num,weight,heaven,max,min,class,nonclass",
          needs,",")
    for(i in needs)  empty2(t,needs[i])
    for(i in r)      header1(t,i,r[i],10000000000)
}
function header1(t,c,val,big,     util,n,isnum) {
    t["cols"]++ 
    t["string"][c]=val
    t[ classp(val) ? "class" : "nonclass" ][c] = 1
    if (! ignorep(val)) t["use"][c]=1
    t["weight"][c] = 1        
    if (split(val,util,/\*/) > 1 ) {
        t["weight"][c]= util[2] 
        val=util[1]  }
    if (nump(val)) {
        isnum = t["num"][c] = 1   
        t["max"   ][c]= big * -1
        t["min"   ][c]= big
        t["heaven"][c] = (1 - hatep(val))
   }
    gsub(/[<\$!\?]/,"",val)
    t["name"][c]= val
    t["col"][val] = c
}
function row(t,arow,    val,r,c) {
    if (! ok(length(arow) == t["cols"],
             "row " t["rows"]+1 " of wrong length")) return 1
    r = ++t["rows"]
    for(c in t["use"]) {
        val = arow[c] 
        t[r][c] = val
        if (val == "?") continue
        if (c in t["num"]) 
            if (ok(val ~ Const["num"] ,
                   "col ["c "]=[" val "] not a number in "row2String(arow))) {
                if(val > t["max"][c]) t["max"][c]=val
                if(val < t["min"][c]) t["min"][c]=val }}
    return r
}
